# ====================================================================
#  (The Brain)
# ====================================================================
cmake_minimum_required(VERSION 3.15)
project(AlgoHub CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_DEBUG_POSTFIX "D")

include(third/depends.cmake)


link_directories(${CMAKE_BINARY_DIR}/lib)
option(BUILD_SHARED "Build algorithms as shared/dynamic libraries (.dll, .so)" ON)
option(BUILD_TESTS "Build the main test executable for all algorithms" ON)

if(BUILD_SHARED)
    set(ALGORITHM_LIBRARY_TYPE SHARED)
else()
    set(ALGORITHM_LIBRARY_TYPE STATIC)
endif()

function(assign_source_group)
    foreach(_source IN ITEMS ${ARGN})
        if (IS_ABSOLUTE "${_source}")
            file(RELATIVE_PATH _source_rel "${CMAKE_CURRENT_SOURCE_DIR}" "${_source}")
        else()
            set(_source_rel "${_source}")
        endif()
        get_filename_component(_source_path "${_source_rel}" PATH)
        string(REPLACE "/" "\\" _source_path_msvc "${_source_path}")
        source_group("${_source_path_msvc}" FILES "${_source}")
    endforeach()
endfunction(assign_source_group)

set(ALL_ALGORITHM_TARGETS "")
set(ALL_ALGORITHM_SOURCES "")
set(ALL_INCLUDE_DIRS "")
set(ALL_ALGORITHM_DEPENDENCIES "")

file(GLOB SUB_CMAKE_FILES "src/*/CMakeLists.txt")
foreach(cmake_file ${SUB_CMAKE_FILES})
    get_filename_component(SUB_DIR ${cmake_file} DIRECTORY)
    add_subdirectory(${SUB_DIR})
endforeach()

set(UNIFIED_TARGET_NAME "algohub")
message(STATUS "Final library target '${UNIFIED_TARGET_NAME}' is ready for use.")
message(STATUS "Build mode: Individual. Building separate libraries.")
add_library(${UNIFIED_TARGET_NAME} INTERFACE)
target_link_libraries(${UNIFIED_TARGET_NAME} INTERFACE ${ALL_ALGORITHM_TARGETS})

if(BUILD_SHARED)
    target_compile_definitions(${UNIFIED_TARGET_NAME} INTERFACE ALGOHUB_BUILD)
    message(STATUS "Building shared libraries, defining ALGOHUB_BUILD for interface target.")
endif()

target_compile_definitions(${UNIFIED_TARGET_NAME} INTERFACE COMPANY_WIDE_FLAG=1)

if(MSVC)
    set_target_properties(${UNIFIED_TARGET_NAME} PROPERTIES FOLDER ${PROJECT_NAME})
endif()

if(BUILD_TESTS)
    message(STATUS "Building tests...")	
    file(GLOB TEST_SOURCES "tests/*.cpp")
    file(GLOB TEST_COMMON_HEADER "tests/common/include/*.h" "tests/common/include/*.hpp")
    file(GLOB TEST_COMMON_SOURCE "tests/common/src/*.cpp" "tests/common/src/*.c")
    foreach(TEST_SOURCE ${TEST_SOURCES})
    	get_filename_component(TEST_NAME ${TEST_SOURCE} NAME_WE)
    	source_group("common" FILES ${TEST_COMMON_HEADER})
    	source_group("common" FILES ${TEST_COMMON_SOURCE})
    	
    	add_executable(${TEST_NAME} ${TEST_SOURCE} ${TEST_COMMON_HEADER} ${TEST_COMMON_SOURCE})
    	target_include_directories(${TEST_NAME} PRIVATE "tests/common/include")
    	target_link_libraries(${TEST_NAME} PRIVATE ${UNIFIED_TARGET_NAME})
    	add_third(${TEST_NAME} libNCore)
    	
    	if(MSVC)
    	    set_target_properties(${TEST_NAME} PROPERTIES FOLDER "Tests")
    	endif()
    endforeach()
else()
    message(STATUS "Skipping test build as per configuration.")
endif()

set_property(GLOBAL PROPERTY USE_FOLDERS ON)